'user strict'
var socket;
var localVideo = document.querySelector("video#localVideo")
var localStream;
var localPC;
var muted = false;
var openVideo = true;
var isShare = false;
var isInRoom = false;
var simulcast = true;
var mirc = document.querySelector("img#mirc")
var camera = document.querySelector("img#camera")
var share = document.querySelector("img#share")
var joinOrleaveRoomButton = document.querySelector("img#joinOrleaveRoom")
var remoteVideoMap = new Map();
var userPositionMap = new Map();
var positionUserMap = new Map();
var videoMap = new Map();
var pcMap = new Map();
var stack = new Stack();
function handlerError(err) {
    console.log(err.name + ":" + err.message);
}
function sleep(numberMillis) {
    var now = new Date();
    var exitTime = now.getTime() + numberMillis;
    while (true) {
        now = new Date();
        if (now.getTime() > exitTime)
            return;
    }
}
async function changeDisplay() {
    localStream = await navigator.mediaDevices.getDisplayMedia({
        video: true
    });
    isShare = true;
    share.src = "../icon/share-on.svg";
    if (openVideo) {
        openVideo = !openVideo;
        camera.src = "../icon/video-off.svg"
    }
    changeMedia();
}
function changeMedia() {
    localVideo.srcObject = localStream;
    let videoTrack = localStream.getVideoTracks()[0];
    var sender = localPC.getSenders().find(function (s) {
        return s.track.kind == videoTrack.kind;
    });
    console.log('found sender:', sender);
    sender.replaceTrack(videoTrack);
}
async function changeUserCamera() {
    localStream = await navigator.mediaDevices.getUserMedia({
        video: {
            facingMode: "user"
        },
        audio: {
            echoCancellation: true,
            noiseSuppression: true
        }
    });
    changeMedia();
}
async function changeEnvironmentCamera() {
    localStream = await navigator.mediaDevices.getUserMedia({
        video: {
            facingMode: "environment"
        },
        audio: {
            echoCancellation: true,
            noiseSuppression: true
        }
    });
    changeMedia();
}
async function initPeerConnection(name, upload) {
    var pc = new RTCPeerConnection(configuration);
    if (!localStream) {
        localStream = await navigator.mediaDevices.getUserMedia({
            video: { width: 1600, height: 900 },
            audio: {
                echoCancellation: true,
                noiseSuppression: true
            }
        });
        localVideo.srcObject = localStream;
        positionUserMap.set("0", id);
        videoMap.set(id, localVideo);
        console.log("get local media:")
        console.log(localStream)
    }

    for (const track of localStream.getTracks()) {
        if (upload) {
            pc.addTrack(track, localStream);
        }
    }
    pc.onicecandidate = (e) => {
        if (e.candidate) {
            sendCandidate(name, e.candidate)
            console.log(Date.parse(new Date())+" you have send candidate " + name)
            console.log(e.candidate)
        }
    }
    pc.ontrack = (e) => {
        var remoteVideo = videoMap.get(name);
        if (!remoteVideo) {
            remoteVideo = stack.pop();
            videoMap.set(name, remoteVideo);
            userPositionMap.set(name, remoteVideo.id.split("remoteVideo")[1]);
            console.log("放置用户" + name + " 位置" + remoteVideo.id.split("remoteVideo")[1]);
            positionUserMap.set(remoteVideo.id.split("remoteVideo")[1], name);
            console.log("位置" + remoteVideo.id.split("remoteVideo")[1] + " 加入用户" + name);
            remoteVideo.srcObject = e.streams[0];
            console.log("get remote stream " + name)
            console.log(e.streams[0])
        }
    }
    return pc;
}
function initLocalWebRtc() {
    initPeerConnection(id, true).then(function (res) {
        localPC = res;
        var offerOptions = {
            iceRestart: true,
            offerToReceiveAudio: false,
            offerToReceiveVideo: false,
        }
        localPC.createOffer(offerOptions).then(function (offer) {
            console.log("you createOffer:")
            console.log(offer)
            if(simulcast){
                offer.sdp = mungeSdpForSimulcasting(offer.sdp)
            }
            console.log("you mungeSdpForSimulcasting:")
            console.log(offer)
            return localPC.setLocalDescription(offer);
        }).then(function () {
            sendOffer(localPC.localDescription);
        }).catch(handlerError);
    });
    keepalive();
}
function connect() {
    // 判断当前浏览器是否支持webSocket
    if (window.WebSocket) {
        socket = new WebSocket(wsUrl);
        // 相当于channel的read事件，ev 收到服务器回送的消息
        socket.onmessage = function (ev) {
            if (ev.data) {
                var data = ev.data;
                if (ev.data == "Connected") {
                    console.log("登陆成功");
                    joinAndPub();
                    return;
                }
                data = JSON.parse(data);
                const response = JSON.stringify(data);
                console.log(response)
                if(data.srs){
                    var targetUserId = data.srs;
                    initPeerConnection(targetUserId, false).then(function (res) {
                        var pc = res;
                        var offerOptions = {
                            offerToReceiveAudio: true,
                            offerToReceiveVideo: true,
                        }
                        pc.createOffer(offerOptions).then(function (offer) {
                            console.log("srs: you createOffer:")
                            console.log(offer)
                            start(offer, targetUserId);
                            pc.setLocalDescription(offer);
                            pcMap.set(targetUserId, pc);
                            console.log("you have received offer from " + display)
                        }).then(function () {
                        }).catch(handlerError);
                    });
                    return;
                }
                if (data.jsep) {
                    var jsep = data.jsep;
                    if (jsep.type == "answer") {
                        localPC.setRemoteDescription(new RTCSessionDescription(jsep));
                        console.log("set remote description" + jsep)
                        return;
                    }
                    if (jsep.type == "offer") {
                        var plugindata = data.plugindata;
                        var data = plugindata.data;
                        var display = data.display;
                        initPeerConnection(display, false).then(function (res) {
                            var pc = res;
                            pc.setRemoteDescription(new RTCSessionDescription(jsep))
                            var answerOptions = {
                                iceRestart: true,
                                answerToReceiveAudio: true,
                                answerToReceiveVideo: true,
                            }
                            pc.createAnswer(answerOptions).then(function (offer) {
                                console.log("you createAnswer:")
                                console.log(offer)
                                return pc.setLocalDescription(offer);
                            }).then(function () {
                                start(pc.localDescription, display)
                                pcMap.set(display, pc);
                                console.log("you have received offer from " + display)
                            }).catch(handlerError);
                        });
                        return;
                    }
                }
                if (data.janus == "event") {
                    data = data.plugindata;
                    data = data.data;
                    if (data.videoroom == "joined") {
                        isInRoom = true;
                        joinOrleaveRoomButton.src = "../icon/leave.svg"
                        initLocalWebRtc();
                    }
                    if (data.publishers) {
                        for (var publishers of data.publishers) {
                            if (publishers.display != id) {
                                console.log("用户" + publishers.display + "加入")
                                joinAndSub(publishers.display);
                            } else {
                                console.log("用户" + publishers.display + "未加入")
                            }
                        }
                    }
                    if (data.leaving) {
                        console.log("用户" + data.leaving + "离开")
                        var position = userPositionMap.get(data.leaving)
                        if (position != "0") {
                            var video = videoMap.get(data.leaving);
                            if (video) {
                                userPositionMap.delete(data.leaving)
                                positionUserMap.delete(position)
                            }
                        } else {
                            var video = videoMap.get(id)
                            if (video) {
                                localVideo.srcObject = video.srcObject;
                                userPositionMap.set("0", id);
                                userPositionMap.set(id, "0");
                            }
                        }
                        if (video) {
                            video.srcObject = null;
                            stack.push(video);
                            videoMap.delete(data.leaving);
                            pcMap.delete(data.leaving);
                        }
                    }
                    if (data.started == "ok") {
                        console.log("用户" + data.display + "开始")
                        substream(data.display, 0);
                    }
                    if (data.started == "srs:ok") {
                        console.log("用户" + data.display + "开始")
                        var pc = pcMap.get(data.display);
                        pc.setRemoteDescription(new RTCSessionDescription(data.srsjsep));
                        pcMap.set(data.display,pc);
                    }
                }
            }
        }
        // 相当于连接开启
        socket.onopen = function (ev) {
            if(!id){
                id = uuid2(16, 16)
            }
            login()
        }
        // 相当于连接关闭
        socket.onclose = function (ev) {
            logout()
        }
    } else {
        alert("当前浏览器不支持webSocket")
    }
}
function prom() {
    room = getQueryVariable("room")
    if(getQueryVariable("simulcast")){
        simulcast = getQueryVariable("simulcast")
    };
    if (room) {
        connect();
    } else {
        room = Math.floor(Math.random() * (360000) + 1000)
        window.location.href = "?room=" + room
    }
}
function changeMuted() {
    if (muted) {
        mirc.src = "../icon/mirc-on.svg"
    } else {
        mirc.src = "../icon/mirc-off.svg"
    }
    muted = !muted;
    doMuted()
}
function changeCamera() {
    if (openVideo) {
        camera.src = "../icon/video-off.svg"
    } else {
        if (isShare) {
            isShare = !isShare;
            share.src = "../icon/share-off.svg"
            changeUserCamera();
        }
        camera.src = "../icon/video-on.svg"
    }
    openVideo = !openVideo;
    doOpenOrCloseCamera()
}
function doMuted() {
    localVideo.srcObject = localStream;
    let audioTrack = localStream.getAudioTracks()[0];
    var sender = localPC.getSenders().find(function (s) {
        return s.track.kind == audioTrack.kind;
    });
    audioTrack.enabled = muted;
    console.log('found sender:', sender);
    sender.replaceTrack(audioTrack);
}
function doOpenOrCloseCamera() {
    localVideo.srcObject = localStream;
    let videoTrack = localStream.getVideoTracks()[0];
    var sender = localPC.getSenders().find(function (s) {
        return s.track.kind == videoTrack.kind;
    });
    videoTrack.enabled = openVideo;
    console.log('found sender:', sender);
    sender.replaceTrack(videoTrack);
}
function changePosition() {
    console.log(this)
    console.log(this.id.split("remoteVideo")[1]);
    if (this.srcObject) {
        var stream = localVideo.srcObject;
        localVideo.srcObject = this.srcObject;
        this.srcObject = stream;
        changeMainVideo(this);
    }
}
function changeMainVideo(remoteVideo) {
    var position = remoteVideo.id.split("remoteVideo")[1];
    var RightUser = positionUserMap.get(position);
    var leftUser = positionUserMap.get("0");
    videoMap.set(RightUser, localVideo);
    userPositionMap.set(RightUser, "0");
    console.log("放置用户" + RightUser + " 位置" + "0");
    positionUserMap.set("0", RightUser);
    console.log("位置" + "0" + " 加入用户" + RightUser);
    if (RightUser != id) {
        substream(RightUser, 2);
    }
    videoMap.set(leftUser, remoteVideo);
    userPositionMap.set(leftUser, position);
    console.log("放置用户" + leftUser + " 位置" + position);
    positionUserMap.set(position, leftUser);
    console.log("位置" + position + " 加入用户" + leftUser);
    if (leftUser != id) {
        substream(leftUser, 0);
    }
}
function initRemoteVideo() {
    for (var i = 8; i > 0; i--) {
        var remoteVideo = document.querySelector("video#remoteVideo" + i)
        remoteVideo.onclick = changePosition
        stack.push(remoteVideo);
    }
}
function joinOrleaveRoom() {
    if (isInRoom) {
        pcMap.forEach(function (value, key) {
            var position = userPositionMap.get(key)
            if (position != "0") {
                var video = videoMap.get(key);
                if (video) {
                    userPositionMap.delete(key)
                    positionUserMap.delete(position)
                }
            } else {
                var video = videoMap.get(id)
                if (video) {
                    localVideo.srcObject = video.srcObject;
                    userPositionMap.set("0", id);
                    userPositionMap.set(id, "0");
                }
            }
            if (video) {
                video.srcObject = null;
                stack.push(video);
                videoMap.delete(key);
                pcMap.delete(key);
            }
        });
        leave();
        joinOrleaveRoomButton.src = "../icon/entry.svg"
        isInRoom = false;
    } else {
        joinAndPub();
    }
}
prom();
initRemoteVideo();
mirc.onclick = changeMuted
share.onclick = changeDisplay
camera.onclick = changeCamera
joinOrleaveRoomButton.onclick = joinOrleaveRoom
// environment.onclick = changeEnvironmentCamera